<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件上传下载系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <style>
        :root {
            --primary-color: #4361ee;
            --primary-hover: #3a0ca3;
            --success-color: #4cc9f0;
            --danger-color: #f72585;
            --warning-color: #f9c74f;
            --bg-color: #f8f9fa;
            --card-bg: #ffffff;
            --text-primary: #212529;
            --text-secondary: #6c757d;
            --border-color: #dee2e6;
            --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
            --shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            --shadow-md: 0 8px 15px rgba(0, 0, 0, 0.1);
            --radius: 8px;
            --radius-lg: 12px;
            --transition: all 0.3s ease;
        }
        
        body {
            background-color: var(--bg-color);
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            color: var(--text-primary);
            line-height: 1.6;
        }
        
        .container {
            max-width: 900px;
            margin-top: 2rem;
            margin-bottom: 2rem;
        }
        
        .header {
            text-align: center;
            margin-bottom: 2.5rem;
            color: var(--text-primary);
        }
        
        .header h1 {
            font-size: 2.5rem;
            font-weight: 700;
            color: var(--primary-color);
            margin-bottom: 0.5rem;
        }
        
        .header p {
            color: var(--text-secondary);
            font-size: 1.125rem;
        }
        
        .card {
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow);
            border: 1px solid var(--border-color);
            overflow: hidden;
            transition: var(--transition);
        }
        
        .card:hover {
            box-shadow: var(--shadow-md);
        }
        
        .card-header {
            background-color: var(--primary-color);
            color: white;
            border-radius: var(--radius-lg) var(--radius-lg) 0 0;
            padding: 1rem 1.5rem;
            font-size: 1.125rem;
            font-weight: 600;
        }
        
        .card-body {
            padding: 2rem;
            background-color: var(--card-bg);
        }
        
        .file-upload-area {
            border: 2px dashed var(--border-color);
            border-radius: var(--radius);
            padding: 3rem 2rem;
            text-align: center;
            cursor: pointer;
            transition: var(--transition);
            background-color: #fafafa;
            position: relative;
        }
        
        .file-upload-area:hover {
            border-color: var(--primary-color);
            background-color: #f8f9ff;
            transform: translateY(-2px);
        }
        
        .file-upload-area.dragover {
            border-color: var(--primary-color);
            background-color: #f3f4ff;
        }
        
        .file-upload-icon {
            font-size: 4rem;
            color: #adb5bd;
            margin-bottom: 1.5rem;
            transition: var(--transition);
        }
        
        .file-upload-area:hover .file-upload-icon {
            color: var(--primary-color);
            transform: scale(1.1);
        }
        
        .file-upload-text {
            color: var(--text-secondary);
            margin-bottom: 1.5rem;
            font-size: 1.125rem;
        }
        
        .file-upload-button {
            background-color: var(--primary-color);
            color: white;
            border: none;
            padding: 0.75rem 2rem;
            border-radius: var(--radius);
            cursor: pointer;
            transition: var(--transition);
            font-size: 1rem;
            font-weight: 500;
            box-shadow: var(--shadow-sm);
        }
        
        .file-upload-button:hover {
            background-color: var(--primary-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow);
        }
        
        .file-list {
            margin-top: 2.5rem;
        }
        
        .file-item {
            display: flex;
            flex-direction: column;
            padding: 1rem;
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            margin-bottom: 1rem;
            transition: var(--transition);
            background-color: var(--card-bg);
        }
        
        .file-item:hover {
            box-shadow: var(--shadow);
            transform: translateY(-2px);
        }
        
        .file-item-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 0.75rem;
        }
        
        .file-info {
            display: flex;
            align-items: center;
            flex: 1;
        }
        
        .file-icon {
            font-size: 2rem;
            color: var(--primary-color);
            margin-right: 1rem;
            width: 2.5rem;
            text-align: center;
        }
        
        .file-details {
            flex: 1;
            min-width: 0;
        }
        
        .file-name {
            font-weight: 600;
            color: var(--text-primary);
            display: block;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-bottom: 0.25rem;
        }
        
        .file-meta {
            font-size: 0.875rem;
            color: var(--text-secondary);
        }
        
        .file-actions {
            display: flex;
            gap: 0.5rem;
        }
        
        .file-action-btn {
            background: none;
            border: none;
            cursor: pointer;
            font-size: 1.25rem;
            color: var(--text-secondary);
            transition: var(--transition);
            padding: 0.5rem;
            border-radius: 50%;
            width: 2.5rem;
            height: 2.5rem;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .file-action-btn:hover {
            background-color: #f8f9fa;
            color: var(--primary-color);
        }
        
        .download-btn:hover {
            color: var(--success-color) !important;
            background-color: #e7f8ff;
        }
        
        .delete-btn:hover {
            color: var(--danger-color) !important;
            background-color: #fff0f3;
        }
        
        .download-progress-container {
            background-color: #f8f9fa;
            padding: 0.75rem;
            border-radius: var(--radius);
            border-top: 1px solid var(--border-color);
            margin-top: 0.75rem;
        }
        
        .progress {
            height: 10px;
            border-radius: 5px;
            overflow: hidden;
            margin-bottom: 0.75rem;
            background-color: #e9ecef;
        }
        
        .progress-bar {
            border-radius: 5px;
            transition: width 0.3s ease;
        }
        
        .progress-info {
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 0.875rem;
        }
        
        .download-progress-text {
            color: var(--text-secondary);
            font-weight: 500;
        }
        
        .btn {
            transition: var(--transition);
            border-radius: var(--radius);
            font-weight: 500;
            display: inline-flex;
            align-items: center;
            gap: 0.5rem;
        }
        
        .btn:hover {
            transform: translateY(-1px);
        }
        
        .btn-group-sm .btn {
            padding: 0.25rem 0.75rem;
            font-size: 0.875rem;
        }
        
        .footer {
            margin-top: 3rem;
            text-align: center;
            color: var(--text-secondary);
            font-size: 0.875rem;
            padding: 1rem 0;
        }
        
        .alert {
            margin-top: 1.5rem;
            border-radius: var(--radius);
            box-shadow: var(--shadow-sm);
            border: none;
        }
        
        .alert-success {
            background-color: #d1fae5;
            color: #065f46;
        }
        
        .alert-danger {
            background-color: #fee2e2;
            color: #991b1b;
        }
        
        .alert-info {
            background-color: #dbeafe;
            color: #1e3a8a;
        }
        
        .alert-warning {
            background-color: #fef3c7;
            color: #92400e;
        }
        
        /* 空状态样式 */
        .empty-state {
            text-align: center;
            padding: 3rem 1rem;
            color: var(--text-secondary);
        }
        
        .empty-state i {
            font-size: 3rem;
            margin-bottom: 1rem;
            opacity: 0.5;
        }
        
        /* 响应式设计 */
        @media (max-width: 768px) {
            .container {
                margin-top: 1rem;
                margin-bottom: 1rem;
                padding: 0 1rem;
            }
            
            .header h1 {
                font-size: 2rem;
            }
            
            .card-body {
                padding: 1.5rem;
            }
            
            .file-upload-area {
                padding: 2rem 1rem;
            }
            
            .file-upload-icon {
                font-size: 3rem;
            }
            
            .file-details {
                margin-right: 0.5rem;
            }
            
            .file-name {
                font-size: 0.875rem;
            }
        }
        
        /* 动画效果 */
        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        .file-item {
            animation: fadeInUp 0.3s ease-out;
        }
        
        /* 按钮加载状态 */
        .btn-loading {
            position: relative;
            pointer-events: none;
        }
        
        .btn-loading::after {
            content: '';
            position: absolute;
            width: 16px;
            height: 16px;
            margin: auto;
            border: 2px solid transparent;
            border-top-color: currentColor;
            border-radius: 50%;
            animation: spin 1s ease-in-out infinite;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>文件上传下载系统</h1>
        </div>
        
        <div class="card">
            <div class="card-header">
                <h2 class="mb-0">上传文件</h2>
            </div>
            <div class="card-body">
                <!-- 上传区域 -->
                <form id="uploadForm" enctype="multipart/form-data" method="post" action="/upload">
                    <div class="file-upload-area" id="dropArea">
                        <div class="file-upload-icon">
                            <i class="fa fa-cloud-upload"></i>
                        </div>
                        <p class="file-upload-text">拖放文件到此处，或</p>
                        <input type="file" id="fileInput" name="file" style="display: none;">
                        <button type="button" class="file-upload-button" onclick="document.getElementById('fileInput').click();">
                            选择文件
                        </button>
                    </div>
                    
                    <!-- 进度条容器 -->
                    <div class="progress-container" style="display: none;">
                        <div class="progress">
                            <div class="progress-bar progress-bar-striped progress-bar-animated bg-info" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
                        </div>
                        <div class="d-flex justify-content-between mt-2">
                            <small id="progressText" class="form-text text-muted">上传准备中...</small>
                            <div class="btn-group">
                                <button id="pauseUploadBtn" class="btn btn-sm btn-warning" style="display: none;">
                                    <i class="fa fa-pause"></i> 暂停
                                </button>
                                <button id="resumeUploadBtn" class="btn btn-sm btn-success" style="display: none;">
                                    <i class="fa fa-play"></i> 继续
                                </button>
                                <button id="cancelUploadBtn" class="btn btn-sm btn-danger" style="display: none;">
                                    <i class="fa fa-times"></i> 取消
                                </button>
                            </div>
                        </div>
                    </div>
                </form>
            </div>
        </div>
        
        <!-- 文件列表 -->
        <div class="card file-list">
            <div class="card-header">
                <h2 class="mb-0">已上传文件</h2>
            </div>
            <div class="card-body">
                <div id="fileListContainer">
                    <!-- 文件列表将通过JavaScript动态加载 -->
                    <p class="text-center text-muted">暂无文件，请先上传文件</p>
                </div>
            </div>
        </div>
        
        <!-- 消息提示 -->
        <div id="messageContainer"></div>
        
        <!-- 页脚 -->
        <div class="footer">
            <p>&copy; 2023 文件上传下载系统 - 简洁高效的文件管理解决方案</p>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        // 初始化页面
        document.addEventListener('DOMContentLoaded', function() {
            loadFileList();
            initDragAndDrop();
            initFileInput();
        });

        // 加载文件列表
        function loadFileList() {
            fetch('/files')
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    const container = document.getElementById('fileListContainer');
                    
                    // 确保files是数组
                    let files = [];
                    if (Array.isArray(data)) {
                        files = data;
                    } else if (data && Array.isArray(data.files)) {
                        files = data.files;
                    }
                    
                    // 按上传时间降序排列
                    files.sort((a, b) => {
                        const timeA = new Date(a.uploadTime || 0).getTime();
                        const timeB = new Date(b.uploadTime || 0).getTime();
                        return timeB - timeA;
                    });
                    
                    if (files.length === 0) {
                        // 显示空状态
                        container.innerHTML = `
                            <div class="empty-state">
                                <i class="fa fa-folder-open-o"></i>
                                <h3>暂无文件</h3>
                                <p>上传文件以开始管理您的文件库</p>
                            </div>
                        `;
                        return;
                    }
                    
                    container.innerHTML = '';
                    files.forEach(file => {
                        try {
                            // 确保文件对象有必要的属性
                            const fileData = {
                                id: file.id || file.fileId || file.file_id || 'unknown',
                                fileName: file.fileName || '未知文件',
                                originalFileName: file.originalFileName || file.fileName || file.file_name || '未知文件',
                                size: file.size || file.fileSize || file.file_size || 0,
                                uploadTime: file.uploadTime || file.upload_time || new Date().toISOString()
                            };
                            
                            // 验证ID有效性
                            if (fileData.id === 'unknown') {
                                console.warn('跳过ID未知的文件项:', file);
                                return;
                            }
                            
                            const fileItem = createFileItem(fileData);
                            container.appendChild(fileItem);
                        } catch (err) {
                            console.error('处理文件项时出错:', err);
                        }
                    });
                })
                .catch(error => {
                    console.error('加载文件列表失败:', error);
                    showMessage(`获取文件列表失败: ${error.message}`, 'danger');
                    // 显示友好的错误状态
                    const container = document.getElementById('fileListContainer');
                    container.innerHTML = `
                        <div class="empty-state">
                            <i class="fa fa-exclamation-circle"></i>
                            <h3>获取文件列表失败</h3>
                            <p>请刷新页面重试或联系管理员</p>
                        </div>
                    `;
                });
        }

        // 创建文件项
        function createFileItem(file) {
            const fileItem = document.createElement('div');
            fileItem.className = 'file-item';
            fileItem.setAttribute('data-file-id', file.id);
            
            // 计算文件大小
            const fileSize = formatFileSize(file.size);
            
            // 根据文件扩展名决定图标
            const extension = file.originalFileName.split('.').pop()?.toLowerCase() || '';
            let fileIcon = 'fa-file-o';
            let iconColor = 'var(--primary-color)';
            
            if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(extension)) {
                fileIcon = 'fa-file-image-o';
                iconColor = '#38b000'; // 绿色
            } else if (['doc', 'docx'].includes(extension)) {
                fileIcon = 'fa-file-word-o';
                iconColor = '#0078d4'; // 蓝色
            } else if (['xls', 'xlsx'].includes(extension)) {
                fileIcon = 'fa-file-excel-o';
                iconColor = '#107c10'; // 深绿色
            } else if (['pdf'].includes(extension)) {
                fileIcon = 'fa-file-pdf-o';
                iconColor = '#dc3545'; // 红色
            } else if (['zip', 'rar', '7z'].includes(extension)) {
                fileIcon = 'fa-file-archive-o';
                iconColor = '#6c757d'; // 灰色
            } else if (['mp3', 'wav', 'flac'].includes(extension)) {
                fileIcon = 'fa-file-audio-o';
                iconColor = '#fd7e14'; // 橙色
            } else if (['mp4', 'avi', 'mov'].includes(extension)) {
                fileIcon = 'fa-file-video-o';
                iconColor = '#6f42c1'; // 紫色
            } else if (['txt', 'md', 'log'].includes(extension)) {
                fileIcon = 'fa-file-text-o';
                iconColor = '#20c997'; // 青绿色
            }
            
            // 创建文件信息HTML - 使用新的样式结构
            // 添加上传状态显示
            const uploadStatus = file.uploadStatus || 'completed'; // 默认已完成
            const statusClasses = {
                'completed': 'badge-success',
                'uploading': 'badge-warning',
                'paused': 'badge-secondary',
                'failed': 'badge-danger'
            };
            const statusText = {
                'completed': '已完成',
                'uploading': '上传中',
                'paused': '已暂停',
                'failed': '上传失败'
            };
            
            fileItem.innerHTML = `
                <div class="file-item-header">
                    <div class="file-info">
                        <div class="file-icon" style="color: ${iconColor};">
                            <i class="fa ${fileIcon}"></i>
                        </div>
                        <div class="file-details">
                            <div class="file-name" title="${file.originalFileName}">${file.originalFileName}</div>
                            <div class="file-meta">
                                <span>${fileSize}</span>
                                <span class="mx-2">•</span>
                                <span>${formatDate(file.uploadTime)}</span>
                                <span class="mx-2">•</span>
                                <span class="badge ${statusClasses[uploadStatus] || 'badge-success'}">${statusText[uploadStatus] || '已完成'}</span>
                            </div>
                        </div>
                    </div>
                    <div class="file-actions">
                        <button class="file-action-btn download-btn" data-file-id="${file.id}" title="下载">
                            <i class="fa fa-download"></i>
                        </button>
                        <button class="file-action-btn delete-btn" data-file-id="${file.id}" title="删除">
                            <i class="fa fa-trash"></i>
                        </button>
                    </div>
                </div>
                <!-- 下载进度条 (初始隐藏) -->
                <div class="download-progress-container" id="downloadProgress-${file.id}" style="display: none;">
                    <div class="progress">
                        <div class="progress-bar bg-primary" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
                    </div>
                    <div class="progress-info">
                        <span class="download-progress-text" id="progressText-${file.id}">准备下载...</span>
                        <div class="btn-group btn-group-sm">
                            <button class="btn btn-secondary pause-download-btn" id="pauseBtn-${file.id}" data-file-id="${file.id}">
                                <i class="fa fa-pause"></i>
                            </button>
                            <button class="btn btn-secondary resume-download-btn" id="resumeBtn-${file.id}" data-file-id="${file.id}" style="display: none;">
                                <i class="fa fa-play"></i>
                            </button>
                            <button class="btn btn-danger cancel-download-btn" id="cancelBtn-${file.id}" data-file-id="${file.id}">
                                <i class="fa fa-times"></i>
                            </button>
                        </div>
                    </div>
                </div>
            `;
            
            // 添加事件监听器（不再使用内联onclick）
            const downloadBtn = fileItem.querySelector('.download-btn');
            const deleteBtn = fileItem.querySelector('.delete-btn');
            const pauseBtn = fileItem.querySelector('.pause-download-btn');
            const resumeBtn = fileItem.querySelector('.resume-download-btn');
            const cancelBtn = fileItem.querySelector('.cancel-download-btn');
            
            if (downloadBtn) {
                downloadBtn.addEventListener('click', function() {
                    downloadFile(file.id, file.originalFileName);
                });
            }
            
            if (deleteBtn) {
                deleteBtn.addEventListener('click', function() {
                    deleteFile(file.id, deleteBtn);
                });
            }
            
            if (pauseBtn) {
                pauseBtn.addEventListener('click', function() {
                    pauseDownload(file.id);
                });
            }
            
            if (resumeBtn) {
                resumeBtn.addEventListener('click', function() {
                    resumeDownload(file.id);
                });
            }
            
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function() {
                    cancelDownload(file.id);
                });
            }
            
            return fileItem;
        }

        // 初始化拖放上传
        function initDragAndDrop() {
            const dropArea = document.getElementById('dropArea');
            
            // 阻止默认拖放行为
            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, preventDefaults, false);
            });
            
            function preventDefaults(e) {
                e.preventDefault();
                e.stopPropagation();
            }
            
            // 高亮效果
            ['dragenter', 'dragover'].forEach(eventName => {
                dropArea.addEventListener(eventName, highlight, false);
            });
            
            ['dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, unhighlight, false);
            });
            
            function highlight() {
                dropArea.classList.add('border-primary');
                dropArea.classList.add('bg-light');
            }
            
            function unhighlight() {
                dropArea.classList.remove('border-primary');
                dropArea.classList.remove('bg-light');
            }
            
            // 处理文件拖放
            dropArea.addEventListener('drop', handleDrop, false);
            
            function handleDrop(e) {
                const dt = e.dataTransfer;
                const files = dt.files;
                
                if (files.length > 0) {
                    uploadFile(files[0]);
                }
            }
        }

        // 初始化文件选择
        function initFileInput() {
            const fileInput = document.getElementById('fileInput');
            fileInput.addEventListener('change', function() {
                if (this.files.length > 0) {
                    uploadFile(this.files[0]);
                }
            });
        }

        // 计算文件MD5（使用FileReader API计算文件内容的MD5摘要）
        function calculateFileMD5(file) {
            // 为了简单起见，我们使用文件名+文件大小+修改时间的组合作为更稳定的标识符
            // 实际项目中应该使用SparkMD5等库计算真正的文件内容MD5
            const fileStats = file.name + '_' + file.size + '_' + file.lastModified;
            let hash = 0;
            for (let i = 0; i < fileStats.length; i++) {
                const char = fileStats.charCodeAt(i);
                hash = ((hash << 5) - hash) + char;
                hash = hash & hash; // Convert to 32bit integer
            }
            return Math.abs(hash).toString(16) + '_' + file.name;
        }

        // 全局上传任务管理
        let currentUploadTask = null;
        
        // 全局取消上传函数
        function cancelUpload() {
            if (currentUploadTask && currentUploadTask.cancel) {
                currentUploadTask.cancel();
            }
        }
        
        // 全局变量定义
        let currentFile = null; // 当前上传的文件引用
        let chunkSize = 1024 * 1024; // 1MB分片
        let totalChunks = 0;
        let identifier = null;
        let currentChunk = 0;
        let isPaused = false;
        let currentXhr = null;
        let uploadedBytes = 0;
        let uploadInProgress = false; // 上传进行中标志
        let isCancelled = false;
        
        // 重置上传状态函数
        function resetUploadState() {
            console.log('重置上传状态');
            // 中止当前进行中的请求
            if (currentXhr) {
                currentXhr.abort();
                currentXhr = null;
            }
            
            // 重置所有状态变量
            currentChunk = 0;
            isPaused = false;
            uploadedBytes = 0;
            uploadInProgress = false;
            isCancelled = false;
            currentFile = null;
            identifier = null; // 重置identifier，确保不会使用旧值
            
            // 重置UI元素
            const progressBar = document.querySelector('.progress-bar');
            if (progressBar) {
                progressBar.style.width = '0%';
                progressBar.setAttribute('aria-valuenow', '0');
            }
            
            const progressText = document.getElementById('progressText');
            if (progressText) {
                progressText.textContent = '0%';
            }
        }
        
        // 上传文件（支持分片上传和暂停继续）
        function uploadFile(file) {
            console.log('开始上传文件:', file.name);
            
            // 重置所有上传相关状态
            resetUploadState();
            
            // 保存文件引用
            currentFile = file;
            
            // 设置基本参数
            chunkSize = 1024 * 1024; // 1MB分片
            totalChunks = Math.ceil(file.size / chunkSize);
            identifier = calculateFileMD5(file);
            uploadInProgress = true; // 标记上传开始
            
            console.log('上传参数设置完成:', {chunkSize, totalChunks, identifier});
            
            // 获取DOM元素
            const progressBar = document.querySelector('.progress-bar');
            const progressContainer = document.querySelector('.progress-container');
            const progressText = document.getElementById('progressText');
            const pauseUploadBtn = document.getElementById('pauseUploadBtn');
            const resumeUploadBtn = document.getElementById('resumeUploadBtn');
            const cancelUploadBtn = document.getElementById('cancelUploadBtn');
            
            // 保存当前上传任务信息
            currentUploadTask = {
                file,
                identifier,
                currentChunk,
                totalChunks,
                isPaused: () => isPaused,
                isCancelled: () => isCancelled,
                cancel: () => {
                    // 1. 先将状态置于暂停状态
                    console.log('设置上传暂停状态（cancel方法）');
                    isPaused = true;
                    
                    if (currentXhr) {
                        currentXhr.abort();
                        currentXhr = null;
                    }
                    
                    // 2. 再设置取消状态
                    console.log('设置上传取消状态（cancel方法）');
                    isCancelled = true;
                    
                    // 3. 删除数据（通知后端清理已上传的分片文件和数据库记录）
                    const cleanupXhr = new XMLHttpRequest();
                    cleanupXhr.open('POST', '/cancel-upload');
                    cleanupXhr.setRequestHeader('Content-Type', 'application/json');
                    cleanupXhr.send(JSON.stringify({ identifier: identifier }));
                    console.log('发送清理请求，清理分片: ' + identifier);
                    
                    // 4. 立即清空进度条
                    if (progressBar) {
                        console.log('清空进度条（cancel方法）');
                        progressBar.style.width = '0%';
                    }
                    if (progressText) {
                        progressText.textContent = '上传已取消';
                    }
                    
                    // 重置所有关键变量
                    currentChunk = 0;
                    identifier = null;
                    file = null;
                    
                    resetUploadUI();
                    showMessage('上传已取消，正在清理资源...', 'info');
                    currentUploadTask = null;
                }
            };
            
            // 重置进度条样式
            if (progressBar) {
                progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated bg-info';
                progressBar.style.width = '0%';
            }
            
            // 先检查文件是否已上传
            checkFileExists(identifier, function(exists, uploadedChunks) {
                if (exists) {
                    showMessage('文件已存在，无需重复上传', 'success');
                    loadFileList();
                    resetUploadUI();
                    return;
                }
                
                // 如果有已上传的分片，从下一个开始
                if (uploadedChunks && uploadedChunks.length > 0) {
                    currentChunk = Math.max(...uploadedChunks) + 1;
                    console.log('从已上传的分片继续: ' + currentChunk);
                }
                
                // 显示进度条和控制按钮
                progressContainer.style.display = 'block';
                pauseUploadBtn.style.display = 'inline-block';
                resumeUploadBtn.style.display = 'none';
                cancelUploadBtn.style.display = 'inline-block';
                
                // 暂停上传
                pauseUploadBtn.onclick = function(event) {
                    if (!uploadInProgress) return;
                    
                    // 阻止事件冒泡和默认行为，防止表单提交
                    if (event) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                    
                    isPaused = true;
                    if (currentXhr) {
                        console.log('暂停上传，中止当前请求');
                        currentXhr.abort();
                        currentXhr = null;
                    }
                    pauseUploadBtn.style.display = 'none';
                    resumeUploadBtn.style.display = 'inline-block';
                    
                    // 更新进度条样式
                    if (progressBar) {
                        progressBar.classList.remove('progress-bar-animated');
                        progressBar.classList.add('bg-warning');
                    }
                    
                    progressText.textContent = `上传已暂停 - 已完成 ${Math.round(((currentChunk + uploadedBytes / chunkSize) / totalChunks) * 100)}%`;
                    showMessage('上传已暂停', 'info');
                };
                
                // 继续上传
                resumeUploadBtn.onclick = function(event) {
                    // 阻止事件冒泡和默认行为，防止表单提交
                    if (event) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                    
                    // 重置状态，允许从取消状态恢复
                    if (isCancelled) {
                        console.log('从取消状态恢复上传');
                        isCancelled = false; // 重置取消状态
                    }
                    
                    if (!uploadInProgress) {
                        uploadInProgress = true; // 如果状态丢失，重新设置
                    }
                    
                    // 验证必需参数，如果缺失则提示用户重新选择
                    if (typeof file === 'undefined' || file === null) {
                        console.error('文件对象不存在');
                        showMessage('请选择要上传的文件', 'warning');
                        resetUploadUI();
                        return;
                    }
                    
                    // 如果缺失其他参数，重新初始化
                    if (typeof identifier === 'undefined' || identifier === null || identifier === '') {
                        console.log('重新生成文件标识符');
                        identifier = generateFileIdentifier(file);
                    }
                    
                    if (typeof totalChunks === 'undefined' || totalChunks === null || isNaN(totalChunks)) {
                        console.log('重新计算总分片数');
                        chunkSize = 1024 * 1024; // 1MB
                        totalChunks = Math.ceil(file.size / chunkSize);
                    }
                    
                    console.log('用户点击继续上传');
                    isPaused = false;
                    pauseUploadBtn.style.display = 'inline-block';
                    resumeUploadBtn.style.display = 'none';
                    
                    // 更新进度条样式
                    if (progressBar) {
                        progressBar.classList.add('progress-bar-animated');
                        progressBar.classList.remove('bg-warning');
                        progressBar.classList.add('bg-info');
                    }
                    
                    // 确保currentChunk是有效数字并转换为整数
                    currentChunk = parseInt(currentChunk);
                    if (isNaN(currentChunk) || currentChunk < 0 || currentChunk >= totalChunks) {
                        console.error('无效的分片索引:', currentChunk);
                        showMessage('继续上传失败：无效的分片索引', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    const currentProgress = Math.round(((currentChunk + uploadedBytes / chunkSize) / totalChunks) * 100);
                    progressText.textContent = `上传中... ${currentProgress}%`;
                    console.log('继续上传，从分片: ' + currentChunk);
                    
                    uploadNextChunk();
                    showMessage('上传已继续', 'info');
                };
                
                // 取消上传
                cancelUploadBtn.onclick = function(event) {
                    // 阻止事件冒泡和默认行为，防止表单提交
                    if (event) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                    
                    // 添加确认弹窗
                    if (!confirm('确定要取消当前上传任务吗？此操作将完全清除所有上传内容，恢复到初始页面状态。')) {
                        console.log('用户取消了确认操作');
                        return;
                    }
                    
                    console.log('用户确认取消上传，开始完全恢复到初始页面状态');
                    
                    // 中止当前XHR请求
                    if (currentXhr) {
                        console.log('中止当前上传请求');
                        currentXhr.abort();
                        currentXhr = null;
                    }
                    
                    // 删除数据（调用后端接口清理已上传的分片）
                    if (identifier) {
                        console.log('调用后端接口清理分片，identifier:', identifier);
                        const cleanXhr = new XMLHttpRequest();
                        cleanXhr.open('POST', '/cancel-upload');
                        cleanXhr.setRequestHeader('Content-Type', 'application/json');
                        cleanXhr.onload = function() {
                            try {
                                const response = JSON.parse(cleanXhr.responseText);
                                if (cleanXhr.status === 200 && response.success) {
                                    console.log('后端分片清理成功:', response.message);
                                } else {
                                    console.warn('后端分片清理失败:', response.message || '未知错误', '状态码:', cleanXhr.status);
                                }
                            } catch (e) {
                                console.error('解析响应失败:', e);
                            }
                        };
                        cleanXhr.onerror = function() {
                            console.error('后端分片清理请求出错，网络错误');
                        };
                        // 添加请求超时处理
                        cleanXhr.timeout = 5000; // 5秒超时
                        cleanXhr.ontimeout = function() {
                            console.warn('后端分片清理请求超时');
                        };
                        cleanXhr.send(JSON.stringify({ identifier: identifier }));
                    } else {
                        console.warn('无法清理分片：缺少identifier');
                    }
                    
                    // 使用统一的重置函数重置状态
                    console.log('使用resetUploadState函数重置所有上传状态');
                    resetUploadState();
                    
                    // 设置取消标志
                    isCancelled = true;
                    
                    // 清除全局任务对象
                    console.log('清除全局上传任务对象');
                    if (window.currentUploadTask) {
                        window.currentUploadTask = null;
                    } else {
                        currentUploadTask = null;
                    }
                    
                    // 完全恢复到初始页面状态
                    // 1. 重置文件选择器
                    const fileInput = document.getElementById('fileInput');
                    if (fileInput) {
                        fileInput.value = '';
                        console.log('重置文件选择器');
                    }
                    
                    // 2. 确保拖放区域可见并恢复初始样式
                    const dropArea = document.getElementById('dropArea');
                    if (dropArea) {
                        dropArea.style.display = 'block';
                        // 移除可能添加的任何高亮或拖拽状态类
                        dropArea.classList.remove('border-primary', 'bg-light', 'dragover');
                        console.log('恢复拖放区域到初始状态');
                    }
                    
                    // 3. 重置表单到初始状态
                    const uploadForm = document.getElementById('uploadForm');
                    if (uploadForm) {
                        uploadForm.reset();
                        console.log('重置上传表单');
                    }
                    
                    // 4. 隐藏进度条容器和所有控制按钮
                    const progressContainer = document.querySelector('.progress-container');
                    if (progressContainer) {
                        progressContainer.style.display = 'none';
                        console.log('隐藏进度条容器');
                    }
                    
                    // 5. 隐藏所有上传控制按钮
                    const pauseUploadBtn = document.getElementById('pauseUploadBtn');
                    const resumeUploadBtn = document.getElementById('resumeUploadBtn');
                    const cancelUploadBtn = document.getElementById('cancelUploadBtn');
                    
                    if (pauseUploadBtn) pauseUploadBtn.style.display = 'none';
                    if (resumeUploadBtn) resumeUploadBtn.style.display = 'none';
                    if (cancelUploadBtn) cancelUploadBtn.style.display = 'none';
                    console.log('隐藏所有上传控制按钮');
                    
                    // 6. 重置进度条和文本
                    const progressBar = document.querySelector('.progress-bar');
                    const progressText = document.getElementById('progressText');
                    
                    if (progressBar) {
                        progressBar.style.width = '0%';
                        progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated bg-info';
                        progressBar.setAttribute('aria-valuenow', '0');
                    }
                    
                    if (progressText) {
                        progressText.textContent = '上传准备中...';
                    }
                    
                    // 7. 清除任何显示的消息
                    const messageContainer = document.getElementById('messageContainer');
                    if (messageContainer) {
                        messageContainer.innerHTML = '';
                        console.log('清除所有消息提示');
                    }
                    
                    const messageDiv = document.getElementById('message');
                    if (messageDiv) {
                        messageDiv.textContent = '';
                        messageDiv.className = 'alert';
                        messageDiv.style.display = 'none';
                    }
                    
                    // 8. 确保上传区域完全可见且没有任何隐藏状态
                    const cardBody = document.querySelector('.card-body');
                    if (cardBody) {
                        // 确保上传区域的直接子元素都正确显示
                        const children = cardBody.children;
                        for (let i = 0; i < children.length; i++) {
                            // 只隐藏进度条容器，其他元素保持默认显示
                            if (children[i].classList.contains('progress-container')) {
                                children[i].style.display = 'none';
                            }
                        }
                    }
                    
                    console.log('页面已完全恢复到初始状态，没有任何上传相关的按钮和操作痕迹');
                };
                
                // 重置上传UI的函数
                function resetUploadUI() {
                    uploadInProgress = false;
                    isPaused = false;
                    isCancelled = false;
                    currentXhr = null;
                    
                    if (progressContainer) progressContainer.style.display = 'none';
                    if (pauseUploadBtn) pauseUploadBtn.style.display = 'none';
                    if (resumeUploadBtn) resumeUploadBtn.style.display = 'none';
                    if (cancelUploadBtn) cancelUploadBtn.style.display = 'none';
                    if (progressBar) {
                        progressBar.style.width = '0%';
                        progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated bg-info';
                    }
                    if (progressText) progressText.textContent = '上传准备中...';
                    
                    // 清除当前上传任务
                    currentUploadTask = null;
                }
                
                function uploadNextChunk() {
                    // 检查所有必需变量是否存在
                    console.log('进入uploadNextChunk函数');
                    console.log('当前上下文变量检查:');
                    console.log('currentChunk原始值:', currentChunk, typeof currentChunk);
                    console.log('totalChunks:', totalChunks, typeof totalChunks);
                    console.log('identifier:', identifier, typeof identifier);
                    console.log('file对象:', file ? '存在' : '不存在');
                    console.log('状态检查 - isCancelled:', isCancelled, 'isPaused:', isPaused);
                    
                    if (isCancelled) {
                        console.log('检测到取消状态，但允许从继续按钮重置');
                        // 如果用户点击了继续，isCancelled应该已经被重置
                        // 这里主要是作为安全检查
                        return;
                    }
                    
                    if (isPaused) {
                        console.log('上传已暂停，等待继续');
                        return; // 如果暂停，则不继续上传
                    }
                    
                    // 验证必需参数存在性
                    if (typeof currentChunk === 'undefined' || currentChunk === null) {
                        console.error('上传失败：分片索引未定义或为空');
                        showMessage('上传失败：系统错误，请重试', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    if (typeof totalChunks === 'undefined' || totalChunks === null) {
                        console.error('上传失败：总分片数未定义或为空');
                        showMessage('上传失败：系统错误，请重试', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    if (typeof identifier === 'undefined' || identifier === null || identifier === '') {
                        console.error('上传失败：文件标识符未定义或为空');
                        showMessage('上传失败：系统错误，请重试', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    // 确保currentChunk是有效的数字
                    currentChunk = parseInt(currentChunk);
                    if (isNaN(currentChunk)) {
                        console.error('上传失败：无效的分片索引', currentChunk);
                        showMessage('上传失败：内部错误', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    if (currentChunk >= totalChunks) {
                        // 所有分片上传完成，调用合并接口
                        console.log('所有分片上传完成，开始合并');
                        pauseUploadBtn.style.display = 'none';
                        resumeUploadBtn.style.display = 'none';
                        cancelUploadBtn.style.display = 'none';
                        mergeChunks(identifier, file.name, file.type);
                        return;
                    }
                    
                    const start = currentChunk * chunkSize;
                    const end = Math.min(start + chunkSize, file.size);
                    const chunk = file.slice(start, end);
                    
                    console.log(`准备上传分片: ${currentChunk}, 范围: ${start}-${end}`);
                    
                    const formData = new FormData();
                    formData.append('file', chunk);
                    
                    // 明确设置所有表单字段
                    const chunkIndexStr = currentChunk.toString();
                    const totalChunksStr = totalChunks.toString();
                    
                    console.log('准备上传分片索引:', chunkIndexStr);
                    console.log('准备上传总分片数:', totalChunksStr);
                    console.log('准备上传标识符:', identifier);
                    
                    // 确保正确添加所有参数
                    formData.append('chunkIndex', chunkIndexStr);
                    formData.append('totalChunks', totalChunksStr);
                    formData.append('identifier', identifier);
                    console.log('添加参数到表单:', 'chunkIndex=' + chunkIndexStr, 'totalChunks=' + totalChunksStr, 'identifier=' + identifier);
                    
                    // 打印最终上传参数
                    console.log('最终上传参数:', {
                        chunkIndex: chunkIndexStr,
                        totalChunks: totalChunksStr,
                        identifier: identifier,
                        fileSize: chunk.size
                    });
                    
                    currentXhr = new XMLHttpRequest();
                    uploadedBytes = 0;
                    
                    // 计算整体进度
                    // 确保currentChunk在继续上传时是有效的
                    if (typeof currentChunk === 'undefined' || currentChunk === null || isNaN(currentChunk)) {
                        console.error('严重错误：currentChunk无效', currentChunk);
                        showMessage('上传参数错误，请重试', 'danger');
                        resetUploadUI();
                        return;
                    }
                    
                    const overallProgress = (currentChunk / totalChunks) * 100;
                    progressBar.style.width = overallProgress + '%';
                    progressText.textContent = `上传中... ${Math.round(overallProgress)}%`;
                    
                    // 监听上传进度
                    currentXhr.upload.addEventListener('progress', function(e) {
                        if (e.lengthComputable) {
                            uploadedBytes = e.loaded;
                            const chunkProgress = (e.loaded / e.total) * 100;
                            const overallProgress = ((currentChunk + chunkProgress/100) / totalChunks) * 100;
                            progressBar.style.width = overallProgress + '%';
                            progressText.textContent = `上传中... ${Math.round(overallProgress)}%`;
                        }
                    });
                    
                    // 上传完成
                    currentXhr.addEventListener('load', function() {
                        try {
                            console.log(`分片 ${currentChunk} 上传响应状态: ${currentXhr.status}`);
                            
                            // 尝试解析响应内容
                            let response = null;
                            try {
                                if (currentXhr.responseText) {
                                    response = JSON.parse(currentXhr.responseText);
                                    console.log('上传响应:', response);
                                }
                            } catch (e) {
                                console.log('响应不是JSON格式:', currentXhr.responseText);
                            }
                            
                            if (currentXhr.status === 200) {
                                console.log(`分片 ${currentChunk} 上传成功`);
                                currentChunk++;
                                uploadedBytes = 0;
                                uploadNextChunk(); // 递归上传下一个分片
                            } else {
                                console.error(`分片 ${currentChunk} 上传失败，状态码: ${currentXhr.status}`);
                                if (!isPaused) { // 只有非暂停情况下才显示错误
                                    // 显示具体错误信息
                                    const errorMessage = response && response.message ? 
                                        `文件上传失败: ${response.message}` : 
                                        '文件上传失败';
                                    showMessage(errorMessage, 'danger');
                                    resetUploadUI();
                                }
                            }
                        } catch (e) {
                            console.error('处理上传响应时发生错误:', e);
                            if (!isPaused && !isCancelled) {
                                showMessage('处理上传响应时发生错误', 'danger');
                                resetUploadUI();
                            }
                        }
                    });
                    
                    // 上传错误或中断
                    currentXhr.addEventListener('error', function() {
                        console.error(`分片 ${currentChunk} 上传发生错误`);
                        if (!isPaused) { // 只有非暂停情况下才显示错误
                            showMessage('文件上传失败', 'danger');
                            resetUploadUI();
                        }
                    });
                    
                    currentXhr.addEventListener('abort', function() {
                        console.log(`分片 ${currentChunk} 上传已中止`);
                        // 中止上传时不显示错误，因为这是用户主动操作
                    });
                    
                    // 发送请求
                    currentXhr.open('POST', '/upload');
                    currentXhr.send(formData);
                }
                
                // 合并文件分片
                function mergeChunks(identifier, fileName, contentType) {
                    // 检查是否已取消
                    if (isCancelled) {
                        console.log('上传已取消，不执行文件合并');
                        resetUploadUI();
                        return;
                    }
                    
                    const xhr = new XMLHttpRequest();
                    
                    // 更新进度显示
                    progressBar.style.width = '100%';
                    progressBar.classList.remove('bg-info');
                    progressBar.classList.add('bg-success');
                    progressText.textContent = '合并文件中...';
                    
                    console.log('开始合并文件分片');
                    
                    // 准备表单数据
                    const formData = new FormData();
                    formData.append('identifier', identifier);
                    formData.append('fileName', fileName);
                    formData.append('contentType', contentType);
                    
                    xhr.onload = function() {
                        // 检查是否已取消
                        if (isCancelled) {
                            resetUploadUI();
                            return;
                        }
                        
                        console.log('合并请求完成，状态码: ' + xhr.status);
                        if (xhr.status === 200) {
                            try {
                                const response = JSON.parse(xhr.responseText);
                                console.log('合并响应: ', response);
                                if (response.success) {
                                    progressBar.classList.remove('progress-bar-animated');
                                    showMessage('文件上传成功', 'success');
                                    loadFileList();
                                    document.getElementById('fileInput').value = '';
                                    // 清除当前上传任务
                                    currentUploadTask = null;
                                } else {
                                    showMessage('文件合并失败: ' + (response.message || '未知错误'), 'danger');
                                }
                            } catch (e) {
                                console.error('解析合并响应失败: ', e);
                                showMessage('文件合并失败: 解析响应错误', 'danger');
                            }
                        } else {
                            showMessage('文件合并失败: HTTP错误 ' + xhr.status, 'danger');
                        }
                        
                        // 重置UI状态
                        setTimeout(() => {
                            resetUploadUI();
                        }, 1000);
                    };
                    
                    xhr.onerror = function() {
                        console.error('合并请求发生网络错误');
                        showMessage('文件合并失败: 网络错误', 'danger');
                        resetUploadUI();
                    };
                    
                    // 发送合并请求
                    xhr.open('POST', '/merge');
                    xhr.send(formData);
                }
                
                // 开始上传第一个分片
                uploadNextChunk();
            });
        }
        
        // 检查文件是否已存在
        function checkFileExists(identifier, callback) {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', '/check?identifier=' + encodeURIComponent(identifier));
            xhr.onload = function() {
                if (xhr.status === 200) {
                    try {
                        const response = JSON.parse(xhr.responseText);
                        callback(response.exists || false, response.uploadedChunks || []);
                    } catch (e) {
                        callback(false, []);
                    }
                } else {
                    callback(false, []);
                }
            };
            xhr.onerror = function() {
                callback(false, []);
            };
            xhr.send();
        }

        // 下载状态管理
        const downloadTasks = {};
        
        // 下载文件（支持暂停继续和取消）
        function downloadFile(fileId, fileName) {
            console.log('开始下载文件:', fileId, fileName);
            
            // 确保fileId有效
            if (!fileId || isNaN(fileId)) {
                console.error('无效的文件ID:', fileId);
                showMessage('下载失败：无效的文件ID', 'danger');
                return;
            }
            
            // 检查是否有正在进行的下载任务
            if (downloadTasks[fileId]) {
                const task = downloadTasks[fileId];
                // 如果任务已暂停，继续下载
                if (task.paused) {
                    resumeDownload(fileId);
                } else if (task.cancelled) {
                    // 如果已取消，重新开始下载
                    delete downloadTasks[fileId];
                    downloadFile(fileId, fileName);
                } else {
                    // 否则暂停下载
                    pauseDownload(fileId);
                }
                return;
            }
            
            // 创建新的下载任务
            const progressContainer = document.getElementById(`downloadProgress-${fileId}`);
            if (!progressContainer) {
                console.error('找不到进度容器元素:', `downloadProgress-${fileId}`);
                showMessage('下载失败：无法创建下载界面元素', 'danger');
                return;
            }
            
            const progressBar = progressContainer.querySelector('.progress-bar');
            const progressText = progressContainer.querySelector('.download-progress-text');
            const pauseBtn = progressContainer.querySelector('.pause-download-btn');
            const resumeBtn = progressContainer.querySelector('.resume-download-btn');
            const cancelBtn = progressContainer.querySelector('.cancel-download-btn');
            
            // 验证所有UI元素都存在
            if (!progressBar || !progressText || !pauseBtn || !resumeBtn || !cancelBtn) {
                console.error('Missing UI elements for download');
                return;
            }
            
            // 显示进度条
            progressContainer.style.display = 'block';
            progressBar.style.width = '0%';
            progressBar.className = 'progress-bar bg-primary';
            progressText.textContent = '下载中... 0%';
            
            // 显示/隐藏按钮
            pauseBtn.style.display = 'inline-block';
            resumeBtn.style.display = 'none';
            cancelBtn.style.display = 'inline-block';
            
            let startTime = Date.now();
            let bytesDownloaded = 0;
            let totalBytes = 0;
            let paused = false;
            let cancelled = false;
            let xhr = null;
            let lastProgressTime = Date.now();
            let lastProgressBytes = 0;
            let currentSpeed = 0;
            
            // 创建下载任务对象
            const task = {
                fileId,
                fileName,
                bytesDownloaded,
                totalBytes,
                paused,
                cancelled,
                xhr,
                startTime,
                lastProgressTime,
                lastProgressBytes,
                currentSpeed,
                progressBar,
                progressText,
                pauseBtn,
                resumeBtn,
                cancelBtn,
                progressContainer
            };
            
            downloadTasks[fileId] = task;
            
            // 开始下载
            startDownload(task);
        }
        
        // 取消下载
        function cancelDownload(fileId) {
            console.log('Cancelling download for file:', fileId);
            const task = downloadTasks[fileId];
            
            if (task) {
                // 设置取消状态
                task.cancelled = true;
                task.paused = false;
                
                // 中止XHR请求
                if (task.xhr) {
                    try {
                        task.xhr.abort();
                        console.log('XHR aborted successfully');
                    } catch (err) {
                        console.error('Error aborting XHR:', err);
                    }
                }
                
                // 更新UI
                if (task.progressText) {
                    task.progressText.textContent = '下载已取消';
                }
                
                if (task.progressBar) {
                    // 移除可能不存在的类
                    task.progressBar.classList.remove('bg-primary', 'bg-info', 'bg-success');
                    task.progressBar.classList.add('bg-danger');
                }
                
                // 更新按钮状态
                if (task.pauseBtn) task.pauseBtn.style.display = 'none';
                if (task.resumeBtn) task.resumeBtn.style.display = 'none';
                if (task.cancelBtn) task.cancelBtn.style.display = 'none';
                
                showMessage('下载已取消', 'info');
                
                // 清理任务（延迟清理，让用户看到状态）
                setTimeout(() => {
                    if (task.progressContainer) {
                        task.progressContainer.style.display = 'none';
                    }
                    // 安全地从任务列表中删除
                    if (downloadTasks[fileId]) {
                        delete downloadTasks[fileId];
                    }
                }, 1500);
            }
        }
        
        // 开始下载
        function startDownload(task) {
            if (task.cancelled) return;
            
            const { fileId, fileName, bytesDownloaded } = task;
            
            task.xhr = new XMLHttpRequest();
            task.xhr.open('GET', `/download/${fileId}?fileName=${encodeURIComponent(fileName)}`);
            task.xhr.responseType = 'blob';
            
            // 设置Range头以支持断点续传
            if (bytesDownloaded > 0) {
                task.xhr.setRequestHeader('Range', `bytes=${bytesDownloaded}-`);
            }
            
            // 监听下载进度
            task.xhr.addEventListener('progress', function(e) {
                // 检查任务是否已取消
                if (task.cancelled || !task.progressBar || !task.progressText) return;
                
                if (e.lengthComputable) {
                    task.totalBytes = e.total;
                    task.bytesDownloaded = bytesDownloaded + e.loaded;
                    const progress = (task.bytesDownloaded / task.totalBytes) * 100;
                    
                    // 更新进度条
                    task.progressBar.style.width = progress + '%';
                    
                    // 计算当前下载速度（使用最近的数据点）
                    const currentTime = Date.now();
                    const timeDiff = (currentTime - task.lastProgressTime) / 1000;
                    const bytesDiff = task.bytesDownloaded - task.lastProgressBytes;
                    
                    if (timeDiff > 1) { // 每秒更新一次速度
                        task.currentSpeed = bytesDiff / timeDiff;
                        task.lastProgressTime = currentTime;
                        task.lastProgressBytes = task.bytesDownloaded;
                    }
                    
                    const speedFormatted = formatFileSize(task.currentSpeed) + '/s';
                    
                    // 计算剩余时间
                    let remainingText = '';
                    if (task.currentSpeed > 0) {
                        const remaining = (task.totalBytes - task.bytesDownloaded) / task.currentSpeed;
                        if (!isNaN(remaining) && isFinite(remaining)) {
                            if (remaining < 60) {
                                remainingText = ` (剩余约 ${Math.ceil(remaining)} 秒)`;
                            } else {
                                remainingText = ` (剩余约 ${Math.ceil(remaining / 60)} 分钟)`;
                            }
                        }
                    }
                    
                    task.progressText.textContent = `下载中... ${Math.round(progress)}% (${speedFormatted})${remainingText}`;
                }
            });
            
            // 下载完成
            task.xhr.addEventListener('load', function() {
                // 检查任务是否已取消
                if (task.cancelled) {
                    console.log('Load event ignored as download was cancelled');
                    return;
                }
                
                if (this.status === 200 || this.status === 206) {
                    try {
                        // 创建Blob对象
                        const blob = new Blob([this.response], { type: this.getResponseHeader('content-type') });
                        
                        // 创建下载链接
                        const link = document.createElement('a');
                        link.href = window.URL.createObjectURL(blob);
                        link.download = fileName;
                        
                        // 模拟点击下载
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                        
                        // 释放URL对象
                        setTimeout(() => {
                            try {
                                window.URL.revokeObjectURL(link.href);
                            } catch (err) {
                                console.warn('Failed to revoke object URL:', err);
                            }
                        }, 100);
                        
                        // 更新UI
                        if (task.progressText) task.progressText.textContent = '下载完成';
                        if (task.progressBar) {
                            task.progressBar.classList.remove('bg-primary', 'bg-info');
                            task.progressBar.classList.add('bg-success');
                        }
                        
                        showMessage(`文件 ${fileName} 下载成功`, 'success');
                    } catch (err) {
                        console.error('Error in download completion:', err);
                        showMessage(`下载完成但处理文件时出错: ${err.message}`, 'danger');
                    }
                    
                    // 清理任务
                    setTimeout(() => {
                        cleanupDownloadTask(task);
                    }, 1500);
                } else {
                    if (!task.cancelled) {
                        showMessage(`下载失败: HTTP ${this.status}`, 'danger');
                        cleanupDownloadTask(task);
                    }
                }
            });
            
            // 下载错误
            task.xhr.addEventListener('error', function() {
                if (!task.paused && !task.cancelled) {
                    showMessage('下载失败：网络错误', 'danger');
                    cleanupDownloadTask(task);
                }
            });
            
            // 处理中止事件
            task.xhr.addEventListener('abort', function() {
                console.log('Download aborted');
                // 确保只有在被取消时才显示取消状态
                if (task.cancelled && task.progressText) {
                    task.progressText.textContent = '下载已取消';
                }
            });
            
            // 发送请求
            task.xhr.send();
        }
        
        // 清理下载任务
        function cleanupDownloadTask(task) {
            // 安全地清理UI状态
            if (task.progressContainer) {
                task.progressContainer.style.display = 'none';
            }
            
            // 重置按钮状态
            if (task.pauseBtn) task.pauseBtn.style.display = 'inline-block';
            if (task.resumeBtn) task.resumeBtn.style.display = 'none';
            if (task.cancelBtn) task.cancelBtn.style.display = 'none';
            
            // 重置进度条
            if (task.progressBar) {
                task.progressBar.style.width = '0%';
                task.progressBar.className = 'progress-bar';
            }
            
            if (task.progressText) {
                task.progressText.textContent = '准备下载...';
            }
            
            // 安全地从任务列表中删除
            if (task.fileId && downloadTasks[task.fileId]) {
                delete downloadTasks[task.fileId];
            }
            
            // 释放XHR对象引用
            if (task.xhr) {
                task.xhr = null;
            }
        }
        
        // 暂停下载
        function pauseDownload(fileId) {
            const task = downloadTasks[fileId];
            if (task && !task.paused && !task.cancelled) {
                task.paused = true;
                try {
                    if (task.xhr) {
                        task.xhr.abort();
                    }
                } catch (err) {
                    console.error('Error pausing download:', err);
                }
                
                // 更新UI元素
                if (task.pauseBtn) task.pauseBtn.style.display = 'none';
                if (task.resumeBtn) task.resumeBtn.style.display = 'inline-block';
                if (task.cancelBtn) task.cancelBtn.style.display = 'inline-block';
                
                if (task.progressText && task.totalBytes > 0) {
                    const progressPercent = Math.round((task.bytesDownloaded / task.totalBytes) * 100);
                    task.progressText.textContent = `下载已暂停 - 已完成 ${progressPercent}%`;
                } else if (task.progressText) {
                    task.progressText.textContent = '下载已暂停';
                }
                
                showMessage('下载已暂停', 'info');
            }
        }
        
        // 继续下载
        function resumeDownload(fileId) {
            const task = downloadTasks[fileId];
            if (task && task.paused && !task.cancelled) {
                task.paused = false;
                task.startTime = Date.now();
                task.lastProgressTime = Date.now();
                task.lastProgressBytes = task.bytesDownloaded;
                
                // 更新UI元素
                if (task.pauseBtn) task.pauseBtn.style.display = 'inline-block';
                if (task.resumeBtn) task.resumeBtn.style.display = 'none';
                if (task.cancelBtn) task.cancelBtn.style.display = 'inline-block';
                
                if (task.progressBar) {
                    task.progressBar.className = 'progress-bar bg-primary';
                }
                
                if (task.progressText && task.totalBytes > 0) {
                    const progressPercent = Math.round((task.bytesDownloaded / task.totalBytes) * 100);
                    task.progressText.textContent = `下载中... ${progressPercent}%`;
                } else if (task.progressText) {
                    task.progressText.textContent = '下载中...';
                }
                
                startDownload(task);
                showMessage('下载已继续', 'info');
            }
        }

        // 删除文件
        function deleteFile(fileId, buttonElement) {
            if (!confirm('确定要删除此文件吗？删除后不可恢复。')) {
                return;
            }
            
            // 确保有buttonElement参数
            if (!buttonElement) {
                // 如果没有传入buttonElement，则尝试通过fileId查找对应的按钮
                const fileItem = document.querySelector(`.file-item[data-file-id="${fileId}"]`);
                if (fileItem) {
                    buttonElement = fileItem.querySelector('.delete-btn');
                }
            }
            
            let originalContent = '';
            // 显示加载状态
            if (buttonElement) {
                originalContent = buttonElement.innerHTML;
                buttonElement.innerHTML = '<i class="fa fa-spinner fa-spin"></i>';
                buttonElement.disabled = true;
            }
            
            // 发送删除请求
            fetch(`/file/${fileId}`, {
                method: 'DELETE',
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(response => {
                // 即使不是JSON响应也接受
                if (!response.ok) {
                    throw new Error('删除文件失败: ' + response.statusText);
                }
                // 尝试解析JSON但不强制要求
                return response.text().then(text => {
                    try {
                        return JSON.parse(text);
                    } catch (e) {
                        return { success: true };
                    }
                });
            })
            .then(data => {
                showMessage('文件删除成功', 'success');
                
                // 立即从DOM中移除文件项
                const fileItem = document.querySelector(`.file-item[data-file-id="${fileId}"]`);
                if (fileItem && fileItem.parentNode) {
                    fileItem.parentNode.removeChild(fileItem);
                }
                
                // 重新加载文件列表以确保数据一致
                setTimeout(() => {
                    loadFileList();
                }, 500);
            })
            .catch(error => {
                showMessage('删除文件失败', 'danger');
                console.error('Error deleting file:', error);
                
                // 恢复按钮状态
                if (buttonElement) {
                    buttonElement.innerHTML = originalContent;
                    buttonElement.disabled = false;
                }
            });
        }

        // 显示消息
        function showMessage(message, type = 'info') {
            const messageContainer = document.getElementById('messageContainer');
            
            const alert = document.createElement('div');
            alert.className = `alert alert-${type} alert-dismissible fade show`;
            alert.role = 'alert';
            alert.innerHTML = `
                ${message}
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            `;
            
            messageContainer.innerHTML = '';
            messageContainer.appendChild(alert);
            
            // 3秒后自动关闭
            setTimeout(() => {
                const bsAlert = bootstrap.Alert.getInstance(alert);
                if (bsAlert) {
                    bsAlert.close();
                } else {
                    alert.remove();
                }
            }, 3000);
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 格式化日期
        function formatDate(dateString) {
            const date = new Date(dateString);
            const now = new Date();
            const diff = now - date;
            
            // 如果是今天
            if (date.toDateString() === now.toDateString()) {
                return '今天 ' + date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
            }
            
            // 如果是昨天
            const yesterday = new Date(now);
            yesterday.setDate(yesterday.getDate() - 1);
            if (date.toDateString() === yesterday.toDateString()) {
                return '昨天 ' + date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
            }
            
            // 其他日期
            return date.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' });
        }
    </script>
</body>
</html>